package com.manager.common.utils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSON;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.RemovalCause;
import com.github.benmanes.caffeine.cache.RemovalListener;
import com.manager.common.constant.ExcelDicSortEnum;
import com.manager.common.constant.MimicryTcpFileType;
import com.manager.common.token.TokenUtils;
import com.manager.model.*;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DataTools {

	private static Map<String,String> tcpSendData = new ConcurrentHashMap<>();

	private static Integer dataNum = 20;

	private static Object stateLock = new Object();

	private static Object exceptionContainerLock = new Object();


	private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

	public static String containerPrefix = "mimic-container";

	private static List<ExceptionContainerInfo> exceptionContainerInfoList = new ArrayList<>();

	private static Cache<String,Object> cache = Caffeine.newBuilder()
			.expireAfterWrite(3, TimeUnit.MINUTES).removalListener(new RemovalListener<String, Object>() {
				@Override
				public void onRemoval(@Nullable String key, @Nullable Object value, @NonNull RemovalCause cause) {

				}
			}).build();

	private static Logger logger = LoggerFactory.getLogger(DataTools.class);

	public static Map<String, List<Dictionary_Data>> dictionaryMap = new ConcurrentHashMap<String, List<Dictionary_Data>>();

	public static Map<String, System_Setting> systemSettingMap = new ConcurrentHashMap<>();

	public static List<Dictionary_Data> allDicList = new ArrayList<>();

	public static List<System_User> adminList = new ArrayList<>();
	
	public static List<Dictionary_Data> getDicDataByGroupId(String groupId){
		List<Dictionary_Data> list = new ArrayList<>();

		if(!dictionaryMap.containsKey(groupId)){
			return list;
		}

		list = dictionaryMap.get(groupId);

		return list;
	}

	public static List<Dictionary_Data> getDicDataByGroupName(String groupName){
		for(String key:dictionaryMap.keySet()){
			List<Dictionary_Data> list = dictionaryMap.get(key);
			if(list == null || list.size() <= 0){
				continue;
			}
			if(groupName.equals(list.get(0).getGroupName())){
				return list;
			}
		}
		return null;
	}

	public static String getDicValByGroupNameAndText(String groupName, String text){
		List<Dictionary_Data> list = getDicDataByGroupName(groupName);
		if(list == null){
			return null;
		}

		for(Dictionary_Data dictionaryData: list){
			if(text.equals(dictionaryData.getText())){
				return dictionaryData.getVal();
			}
		}
		return null;
	}

	public static String getDicTextByGroupIdAndVal(String groupId, String val){
		List<Dictionary_Data> list = getDicDataByGroupId(groupId);
		for(Dictionary_Data dictionaryData: list){
			if(dictionaryData.getVal().equals(val)){
				return dictionaryData.getText();
			}
		}
		return null;
	}

	public static Integer getDicOrderNumByGroupIdAndVal(String groupId,String val){
		List<Dictionary_Data> list = getDicDataByGroupId(groupId);
		for(Dictionary_Data dictionaryData: list){
			if(dictionaryData.getVal().equals(val)){
				return dictionaryData.getOrderNum();
			}
		}
		return Integer.MIN_VALUE;
	}

	public static List<Dictionary_Data> getDicTextByGroupIdAndValList(String groupId, String val){
		List<Dictionary_Data> list = getDicDataByGroupId(groupId);
		List<Dictionary_Data> result = new ArrayList<>();
		for(Dictionary_Data dictionaryData: list){
			if(dictionaryData.getVal().equals(val)){
				result.add(dictionaryData);
			}
		}
		return result;
	}

	public static Dictionary_Data getDicTextByGroupIdAndValOne(String groupId, String val){
		List<Dictionary_Data> list = getDicDataByGroupId(groupId);
		List<Dictionary_Data> result = new ArrayList<>();
		for(Dictionary_Data dictionaryData: list){
			if(dictionaryData.getVal().equals(val)){
				return dictionaryData;
			}
		}
		return null;
	}

	public static Dictionary_Data getDicByParentIdAndText(String parentId,String groupId,String text){
		List<Dictionary_Data> list = getDicDataByGroupId(groupId);
		for(Dictionary_Data dictionaryData: list){
			if(dictionaryData.getText().equals(text) && parentId.equals(dictionaryData.getpId())){
				return dictionaryData;
			}
		}
		return null;
	}

	public static List<Dictionary_Data> getChildrenDicByParentId(String parentId){
		List<Dictionary_Data> list = new ArrayList<>();
		if(StringUtils.isEmpty(parentId)){
			return list;
		}
		for(Dictionary_Data dic: allDicList){
			if(parentId.equals(dic.getpId())){
				list.add(dic);
			}
		}
		return list;
	}

	public static List<Dictionary_Data> getDicValByGroupIdAndText(String groupId,String text){
		List<Dictionary_Data> list = getDicDataByGroupId(groupId);
		List<Dictionary_Data> result = new ArrayList();
		for(Dictionary_Data dictionaryData: list){
			if(dictionaryData.getText().equals(text)){
				result.add(dictionaryData);
			}
		}
		return result;
	}

	public static  String getParentTextByParentGroupIdAndChildText(String parentGroupId,String childText){
		List<Dictionary_Data> parentList = getDicDataByGroupId(parentGroupId);
		if(parentList.size() <= 0){
			return "";
		}
		for(Dictionary_Data parentDicData:parentList){
			List<Dictionary_Data> childList = getChildrenDicByParentId(parentDicData.getId());
			for(Dictionary_Data childDicData:childList){
				if(childDicData.getText().equals(childText)){
					return  parentDicData.getText();
				}
			}
		}
		return "";
	}
	public static String getSystemSettingStringValByKey(String key){
		System_Setting systemSetting = systemSettingMap.get(key);
		if(systemSetting == null){
			return "";
		}
		return systemSettingMap.get(key).getSystemVal();
	}

	public static Integer getSystemSettingIntValByKey(String key){
		System_Setting systemSetting = systemSettingMap.get(key);
		if(systemSetting == null){
			return null;
		}
		return Integer.valueOf(systemSetting.getSystemVal());
	}

	public static Long getSystemSettingLongValByKey(String key){
		System_Setting systemSetting = systemSettingMap.get(key);
		if(systemSetting == null){
			return null;
		}
		return Long.valueOf(systemSetting.getSystemVal());
	}

	public static Double getSystemSettingDoubleValByKey(String key){
		System_Setting systemSetting = systemSettingMap.get(key);
		if(systemSetting == null){
			return null;
		}
		return Double.valueOf(systemSetting.getSystemVal());
	}

	public static void setSystemSettingDoubleValByKey(String key,System_Setting systemSetting){
		systemSettingMap.put(key,systemSetting);
	}

	public static List<Dictionary_Data> getDicDataByGroupIdAndOrder(String groupId,String order){
		List<Dictionary_Data> list = new ArrayList<>();
		if(!dictionaryMap.containsKey(groupId)){
			return list;
		}
		if(order.equals(ExcelDicSortEnum.DESC.getEnDesc())){
			list = dictionaryMap.get(groupId);
		}else{
			//Collections.reverse(list);
			for(int i = dictionaryMap.get(groupId).size() - 1 ; i >= 0;i--){
				list.add(dictionaryMap.get(groupId).get(i));
			}
		}
		return list;
	}

	public static   String getSerialNumber(){
		String businessSerialNumber = DateTools.getCurrentDateString("yyyyMMddHHmmssSSS");
		businessSerialNumber += generateSmsValidateCode(5);
		return businessSerialNumber;
	}

	public static  String generateSmsValidateCode(int len){
		Random random = new Random();
		StringBuffer stringBuffer = new StringBuffer();
		for(int i = 0;i < len;i++){
			stringBuffer.append(random.nextInt(10));
		}
		return stringBuffer.toString();
	}

	public static void removeSystemSettingDoubleValByKey(String key){
		systemSettingMap.remove(key);
	}

	public static boolean checkWebSocketSessionExist(String serialNumber){
		return tcpSendData.containsKey(serialNumber);
	}

	public static String getWebSessionId(String serialNumber){
		return tcpSendData.get(serialNumber);
	}

	public static void putWebSessionId(String serialNumber){
		if(!TokenUtils.isLogin()){
			return;
		}
		System_User systemUser = TokenUtils.getLoginUser();
		if(systemUser == null){
			return;
		}
		tcpSendData.put(serialNumber,systemUser.getId());
	}

	public static void putCacheData(String key,JSONObject value){
		cache.put(key,value);
	}

	public static void putStateCacheData(JSONObject value){
		synchronized (stateLock){
			/*long timestamp = value.getLong("timestamp") * 100;
			String gatherDate = sdf.format(new Date(timestamp));*/
			value.put("gatherDate",sdf.format(new Date()));
			JSONArray jsonArray = getCacheData(MimicryTcpFileType.STATE_COUNT.getEnDesc());
			if(jsonArray == null){
				jsonArray = new JSONArray();
			}if(jsonArray.size() >= dataNum){
				while (jsonArray.size() >= dataNum){
					jsonArray.remove(0);
				}
			}
			jsonArray.add(value);
			cache.put(MimicryTcpFileType.STATE_COUNT.getEnDesc(),jsonArray);
		}
	}

	public static <T> T getCacheData(String key){
		return (T)cache.getIfPresent(key);
	}

	public static synchronized List<ExceptionContainerInfo> getExceptionContainers(){
		return exceptionContainerInfoList;
	}

	public static synchronized void putExceptionContainers(String content){
		JSONObject jsonObject = JSONObject.fromObject(content);
		exceptionContainerInfoList.clear();
		JSONArray jsonArray = jsonObject.getJSONArray("containers");
		for(int i = 0;i < jsonArray.size();i++){
			ExceptionContainerInfo exceptionContainerInfo =
					(ExceptionContainerInfo) JSONObject.toBean(jsonArray.getJSONObject(i),ExceptionContainerInfo.class);
			exceptionContainerInfoList.add(exceptionContainerInfo);
		}
	}
}
